#ifndef _AUTHSOCKET_H
#define _AUTHSOCKET_H

class ClientListener;

#pragma pack(1)

typedef struct {
	unsigned char   cmd;
	unsigned char  error;
	unsigned short  size;
	unsigned char   gamename[4];
	unsigned char   version1;
	unsigned char   version2;
	unsigned char   version3;
	unsigned short  build;
	unsigned char   platform[4];
	unsigned char   os[4];
	unsigned char   country[4];
	unsigned int  timezone_bias;
	unsigned int  ip;
	unsigned char   I_len;
	unsigned char   I[50];
} sAuthLogonChallenge_C;

typedef struct {
	unsigned char	cmd;
	unsigned char	A[32];
	unsigned char   M1[20];
	unsigned char   crc_hash[20];
	unsigned char   number_of_keys;
	unsigned char   unk;
} sAuthLogonProof_C;

#pragma pack()

struct PacketHandler
{
	void (AuthSocket::*method)(RealmPacket&);
};

enum LogonOps
{
	CMSG_CHALLENGE		= 0x00,
	CMSG_PROOF			= 0x01,
	CMSG_LISTREALMS		= 0x10,
	MAX_LOPS
};

struct Account;

class DLL_EXPORT AuthSocket : public CThread
{
	friend class ClientListener;
	SOCKET m_socket;
	set<RealmPacket*> m_readbuffer;
	set<RealmPacket*> m_writebuffer;
	Mutex m_readlock;
	Mutex m_writelock;
	Account* m_account;
	bool m_authenticated;

	BigNumber N, s, g, v;
	BigNumber b, B;
	BigNumber rs;
	BigNumber m_sessionkey;

	PacketHandler* hndl;
	sAuthLogonChallenge_C m_challenge;

	void HandleChallenge(RealmPacket&);
	void HandleReconnectChallenge(RealmPacket&);
	void HandleProof(RealmPacket&);
	void HandleReconnectProof(RealmPacket&);
	void HandleRealmList(RealmPacket&);
	AuthSocket();
	~AuthSocket();
	void SendCError(ui8 err);
	void SendPError(ui8 err, ui8* M);
public:
	void Remove()
	{
		ThreadState = 0;
	}
	void Loop();
};

#endif